﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using Model.ApiModel.ApiGroup;
using Swashbuckle.AspNetCore.Filters;
using System;
using System.IO;
using System.Linq;

namespace Extensions.Extensions
{

    public static class SwaggerSetUp
    {
        /// <summary>
        ///  Swagger分组配置
        /// </summary>
        /// <param name="service"></param>
        public static void AddSwaggerSetUp(this IServiceCollection services)
        {
            services.AddSwaggerGen(options =>
            {
                //遍历ApiGroupNames所有枚举值生成接口文档，Skip(1)是因为Enum第一个FieldInfo是内置的一个Int值
                typeof(ApiGroupNames).GetFields().Skip(1).ToList().ForEach(f =>
                {
                    //获取枚举值上的特性
                    var info = f.GetCustomAttributes(typeof(GroupInfoAttribute), false).OfType<GroupInfoAttribute>().FirstOrDefault();
                    options.SwaggerDoc(f.Name, new OpenApiInfo
                    {
                        Title = info?.Title,
                        Version = info?.Version,
                        Description = info?.Description
                    });
                });
                //没有加特性的分到这个NoGroup上
                options.SwaggerDoc("NoGroup", new OpenApiInfo
                {
                    Title = "Others"
                });
                //判断接口归于哪个分组
                options.DocInclusionPredicate((docName, apiDescription) =>
                {
                    if (docName == "NoGroup")
                    {
                        //当分组为NoGroup时，只要没加特性的都属于这个组
                        return string.IsNullOrEmpty(apiDescription.GroupName);
                    }
                    else
                    {
                        return apiDescription.GroupName == docName;
                    }
                });
                //添加生成文档
                //下面使用IncludeXmlComments方法加载注释，第二个参数true表示注释文件包含了控制器的注释，如果不包含控制器注释（如引用的其他类库），可以将它置为false
                var file = Path.Combine(AppContext.BaseDirectory, "Api.xml");  // xml文档绝对路径
                var path = Path.Combine(AppContext.BaseDirectory, file);
                options.IncludeXmlComments(path, true); // true : 显示控制器层注释
                options.OrderActionsBy(o => o.RelativePath); // 对action的名称进行排序，如果有多个，就可以看见效果了。

                // 开启小锁
                options.OperationFilter<AddResponseHeadersFilter>();
                options.OperationFilter<AppendAuthorizeToSummaryOperationFilter>();

                // 在header中添加token，传递到后台
                options.OperationFilter<SecurityRequirementsOperationFilter>();

                options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
                {
                    Description = "JWT授权,直接在下框中输入Bearer Token（注意两者之间是一个空格）",
                    Name = "Authorization",//jwt默认的参数名称
                    In = ParameterLocation.Header,//jwt默认存放Authorization信息的位置(请求头中)
                    Type = SecuritySchemeType.ApiKey,
                });
            });

        }

    }
}
